package com.kkwrite.regimen.provider.service.user;

import com.kkwrite.regimen.common.constant.DeletedEnum;
import com.kkwrite.regimen.common.constant.GenderEnum;
import com.kkwrite.regimen.common.constant.LanguageEnum;
import com.kkwrite.regimen.common.constant.SortTypeEnum;
import com.kkwrite.regimen.common.constant.UserLevelEnum;
import com.kkwrite.regimen.common.constant.UserTypeEnum;
import com.kkwrite.regimen.common.entity.dto.BaseDTO;
import com.kkwrite.regimen.common.entity.dto.OutDTO;
import com.kkwrite.regimen.common.entity.dto.login.InviterInfoDTO;
import com.kkwrite.regimen.common.entity.dto.user.PageableUserDTO;
import com.kkwrite.regimen.common.entity.dto.user.RegUserDTO;
import com.kkwrite.regimen.common.entity.dto.user.RegUserInDTO;
import com.kkwrite.regimen.common.entity.dto.user.RegUserOutDTO;
import com.kkwrite.regimen.common.entity.dto.user.UserOutDTO;
import com.kkwrite.regimen.provider.domain.RegUserDO;
import com.kkwrite.regimen.provider.exception.RegimenProviderException;
import com.kkwrite.regimen.provider.exception.ServiceException;
import com.kkwrite.regimen.provider.repository.RegUserRepository;
import com.kkwrite.regimen.provider.stream.dto.RewardPointDTO;
import com.kkwrite.regimen.provider.stream.service.RewardPointService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static com.kkwrite.regimen.common.constant.Constant.BOOLEAN_STRING_FALSE;
import static com.kkwrite.regimen.common.constant.Constant.BOOLEAN_STRING_TRUE;

/**
 * Created by lisha on 2018/7/11 21:16.
 *
 * @author lisha
 */
@Service("regUserService")
public class UserServiceImpl implements UserService {
    @Resource(name = "regUserRepository")
    private RegUserRepository userRepository;
    @Resource
    private RewardPointService rewardPointService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseDTO saveUser(RegUserDTO userDTO) {
        BaseDTO baseDTO = new BaseDTO();
        // 查看该user是否已存在，若存在，返回userId
        RegUserDO queriedUser = userRepository.findByOpenId(userDTO.getOpenId());
        if (queriedUser != null) {
            baseDTO.setCode("0");
            baseDTO.setMessage(String.valueOf(queriedUser.getUserId()));
            return baseDTO;
        }
        // 保存一个新的user
        RegUserDO userDO = new RegUserDO();
        userDO.setAccount(userDTO.getOpenId());
        userDO.setGender(GenderEnum.UNKNOWN.getValue());
        userDO.setOpenId(userDTO.getOpenId());
        userDO.setUserType(UserTypeEnum.TYPE_NORMAL.getTypeValue());
        userDO.setUserLevel(UserLevelEnum.LEVEL_NORMAL.getLevelValue());
        userDO.setUserScore(0);
        userDO.setLanguage(LanguageEnum.CHINESE_SIMPLIFIED.getValue());
        userDO.setDeleted(DeletedEnum.UN_DELETED.getValue());
        userDO = userRepository.save(userDO);
        if (userDO.getUserId() == null) {
            throw new RegimenProviderException("user插入用户表失败");
        }
        if (!rewardPointService.send(new RewardPointDTO(userDO.getUserId(), 100, "首次登录奖励积分"))) {
            throw new RegimenProviderException("user插入用户表失败");
        }
        baseDTO.setCode("0");
        baseDTO.setMessage(String.valueOf(userDO.getUserId()));
        return baseDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RegUserOutDTO updateUser(RegUserInDTO inDTO) {
        if (inDTO.getUserId() == null) {
            return new RegUserOutDTO("false", "userId为空");
        }
        RegUserDO queriedDO = userRepository.findById(inDTO.getUserId()).orElseThrow(NullPointerException::new);
        try {
            com.kkwrite.regimen.provider.util.BeanUtils.copyPropertiesSkipNull(inDTO, queriedDO);
        } catch (IllegalAccessException e) {
            throw new ServiceException(e);
        }
        if (!StringUtils.isBlank(inDTO.getGender())) {
            queriedDO.setGender(GenderEnum.findValue(inDTO.getGender()));
        }
        if (!StringUtils.isBlank(inDTO.getLanguage())) {
            queriedDO.setLanguage(LanguageEnum.findValue(inDTO.getLanguage()));
        }
        userRepository.saveAndFlush(queriedDO);
        return new RegUserOutDTO("true", "执行成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class, readOnly = true)
    public OutDTO<UserOutDTO> queryUser(String userId) {
        RegUserDO userDO = userRepository.findById(Integer.valueOf(userId)).orElse(null);
        if (userDO == null) {
            return OutDTO.of(BOOLEAN_STRING_FALSE, "指定的用户不存在", null, null);
        }
        UserOutDTO out = new UserOutDTO();
        BeanUtils.copyProperties(userDO, out);
        out.setGender(GenderEnum.findGender(userDO.getGender()));
        out.setUserType(UserTypeEnum.findTypeName(userDO.getUserType()));
        out.setUserLevel(UserLevelEnum.findLevelName(userDO.getUserLevel()));
        out.setUserScore(String.valueOf(userDO.getUserScore()));
        out.setLanguage(LanguageEnum.findLanguageName(userDO.getLanguage()));
        return OutDTO.of(BOOLEAN_STRING_TRUE, "OK", "OK", out);
    }

	@Override
	public PageableUserDTO queryUserByInviterId(Integer page, Integer size,
			Long inviterId, Integer sortType) {
		Sort.Direction direction = Sort.Direction.DESC;
		if (SortTypeEnum.POSITIVE_SEQUENCE.getValue().equals(sortType)) {
			direction = Sort.Direction.ASC;
		}
		Pageable pageable = new PageRequest(page, size, new Sort(direction,
				"gmtCreate"));
		RegUserDO regUserDO = new RegUserDO();
		regUserDO.setInviterId(inviterId);
		regUserDO.setInviteFlag(1);//1是用户邀请，2是店铺邀请
		Page<RegUserDO> pageData = userRepository.findAll(
				Example.of(regUserDO), pageable);
		PageableUserDTO pageableUserDto = new PageableUserDTO();
		pageableUserDto.setTotalPages(pageData.getTotalPages());
		pageableUserDto.setTotalElements(pageData.getTotalElements());
		List<UserOutDTO> userOutDtoList = new ArrayList<UserOutDTO>();
		if (pageData.getContent() != null) {
			pageData.getContent().forEach((recordDo) -> {
				UserOutDTO userOutDto = new UserOutDTO();
				BeanUtils.copyProperties(recordDo, userOutDto);
				userOutDtoList.add(userOutDto);
			});
		}
		pageableUserDto.setRecordList(userOutDtoList);
		System.out.println("邀请明细List:" + pageableUserDto.toString());
		return pageableUserDto;
	}

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveInviter(InviterInfoDTO infoDTO, Integer userId) {
        RegUserDO userDO = userRepository.findById(userId).orElseThrow(() -> new RuntimeException("该用户不存在"));
        if (userDO.getInviterId() != null) {
            throw new ServiceException("邀请人已绑定");
        }
        int flag = infoDTO.getInviteFlag();
        String code = infoDTO.getInviteCode();
        userDO.setInviteFlag(flag);
        userDO.setInviterId(Long.valueOf(code));
        userRepository.save(userDO);
        if (flag == 1) {
            // 用户邀请，奖励邀请者积分
            if (!rewardPointService.send(new RewardPointDTO(Integer.valueOf(code), 50, "邀请用户登录"))) {
                throw new ServiceException("消息发送失败");
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class, readOnly = true)
    public RegUserDO findById(int userId) {
        return userRepository.findById(userId).orElseThrow(() -> new RuntimeException("该用户不存在！"));
    }

}
